<?php
define( 'strmax', 255 );

class Form {
    
  private $html = '';
  private $fields = array();
  private $uploads = array();
  private $arr = array();
  private $submit = array();
  
  public $message = '';
  
  public $method = 'post';
  public $elems = array();
  public $table = '';
  public $name = '';
  
  
  public function __construct($table='', $id=0) {
    $this->table = $table;
    $this->arr['id'] = $id;
    if ( $id ) {
      $sql = "SELECT * FROM `::1` WHERE `id`=':i2'";
      $this->arr = db::q($sql, $this->table, $id)->assoc();
    }
  }
  
  public function text($title, $name, $value='', $class='', $style='') {
    $tmp = new Template( 'form_input' );
    $tmp->assign( 'type',    'text' );
    $tmp->assign( 'title',   $title );
    $tmp->assign( 'name',    $name  );
    $tmp->assign( 'value',   $value );
    $tmp->assign( 'style',   $style );
    $tmp->assign( 'class',   $class );
    $this->elems[$name] = $tmp;
    $this->fields[$name] = $value;
  }
  
  public function str($title, $name, $value = "", $length = strmax) {
    $tmp = new Template( 'form_input' );
    $tmp->assign( 'type',    'str'   );
    $tmp->assign( 'title',   $title  );
    $tmp->assign( 'name',    $name   );
    $tmp->assign( 'value',   $value  );
    $tmp->assign( 'length',  $length );
    $this->elems[$name] = $tmp;
    $this->fields[$name] = $value;
  }
  
  public function hidden($name, $value = "", $void=true ) {
    $tmp = new Template( 'form_input' );
    $tmp->assign( 'type',    'hidden' );
    $tmp->assign( 'name',    $name    );
    $tmp->assign( 'value',   $value   );
    $this->elems[$name] = $tmp;
    if (!$void) $this->fields[$name] = $value;
  }
  
  public function file($title, $text = "", $name = "filename") {
    $tmp = new Template( 'form_input' );
    $tmp->assign( 'title',   $title );
    $tmp->assign( 'type',    'file' );
    $tmp->assign( 'name',    $name  );
    $tmp->assign( 'text',    $text  );
    $this->elems[$name] = $tmp;
  }
  
  public function check($title, $name, $checked = false) {
    $tmp = new Template( 'form_input' );
    $tmp->assign( 'type',      'check'  );
    $tmp->assign( 'title',     $title   );
    $tmp->assign( 'name',      $name    );
    $tmp->assign( 'value',     $checked );
    $this->elems[$name] = $tmp;
    $this->fields[$name] = $checked+0;
    if (!isset($_POST[$name])) $_POST[$name] = 0;
  }
  
  public function select($title, $name, $value = "", $val, $op, $void=false) {
    $tmp = new Template( 'form_input' );
    $tmp->assign( 'type',    'select' );
    $tmp->assign( 'title',   $title );
    $tmp->assign( 'name',    $name  );
    $tmp->assign( 'value',   $value );
    $tmp->assign( 'val',     $val );
    $tmp->assign( 'op',      $op );
    $this->elems[$name] = $tmp;
    if (!$void) $this->fields[$name] = $value;
  }
  
  public function select_relation( $sql, $title, $name, $value = "", $allow_null=true, $void=false ) {
    $val = array();
    $op  = array();
    if ($allow_null) {
      $val[] = 0;
      $op[] = 'none';
    }
    $res = db::q( $sql );
    while ( list( $val[], $op[] ) = $res->row() ) {}
    array_pop($val);
    array_pop($op);
    $this->select( $title, $name, $value, $val, $op, $void );
  }
  
  public function submit($title = "Сохранить", $name = "sub") {
    $this->submit[] = $name;
    $tmp = new Template( 'form_input' );
    $tmp->assign( 'type',    'submit' );
    $tmp->assign( 'title',   ' ' );
    $tmp->assign( 'name',    $name  );
    $tmp->assign( 'value',   $title );
    $this->elems[$name] = $tmp;
  }
  
  /**
   * Get html template for output
   * @return Template
   */
  public function output() {
    foreach ( $this->elems as $fld => $e ) {
      if ( $this->submited() && !in_array($fld, $this->submit) && isset($_POST[$fld]) ) {
        $e->assign('value', $_POST[$fld]);
      } elseif ( isset($this->arr[$fld]) ) {
        $e->assign('value', $this->arr[$fld]);
      }
    }
    $html = new Template('form');
    $html->assign( 'name',     $this->name );
    $html->assign( 'method',   $this->method );
    $html->assign( 'content',  implode( '', $this->elems ) );
    $html->assign( 'message',   $this->message );
    return $html;
  }

  public function process( $silent=false ) {
    if ($this->submited()) {
      foreach ( $this->fields as $fld => $val ) {
        if ( $this->arr['id'] ) {
          if ( isset($_POST[$fld]) ) $f[] = " `".$fld."`='".addslashes(isset($_POST[$fld])?$_POST[$fld]:$val)."' ";
        } else {
          $f[] = '`'.$fld.'`';
          $v[] = "'".addslashes($_POST[$fld]?$_POST[$fld]:$val)."'";
        }
      }
      if ( $this->arr['id'] ) {
        $sql = "UPDATE `::1` SET ".implode(',', $f)." WHERE `id`='".$this->arr['id']."'";
      } else {
        $sql = "INSERT INTO `::1` ( ".implode(',', $f)." ) VALUES ( ".implode(',', $v)." )";
      }
      $ok = db::q($sql, $this->table)->ready();
      if ( !$this->arr['id'] ) $this->arr['id'] = db::inserted();
      if ( !$silent ) {
        if ( $ok ) {
          $this->message = '<p>Данные сохранены</p>';
        } else {
          $this->message = '<p>Данные _не_ сохранены</p>'.db::$error;
        }
      }
    }
  }

  
  public function __toString() {
    return $this->output()->process();
  }
 
  public function id() {
    return $this->arr['id'];
  }
  
  private function submited() {
    foreach( $this->submit as $sub ) {
      if ( array_key_exists( $sub, $_POST ) ) return true;
    }
    return false;
  }
}
?>